package com.zff.rental.config;

import com.zff.rental.common.Result;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author HCY
 */
@ControllerAdvice
public class ResultTimingAdvice implements ResponseBodyAdvice<Object> {
    /**
     * 拦截器：只负责记录接口开始时间
     */
    public static class ResponseTimeInterceptor implements HandlerInterceptor {
        private static final String START_TIME_ATTR = "startTime";

        @Override
        public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {
            request.setAttribute(START_TIME_ATTR, System.currentTimeMillis());
            return true;
        }
    }


    @Override
    public boolean supports(MethodParameter returnType, @NotNull Class<? extends HttpMessageConverter<?>> converterType) {
        // 只处理返回类型是 Result 的接口
        return returnType.getParameterType() == Result.class;
    }

    @Override
    public Object beforeBodyWrite(Object body,
                                  @NotNull MethodParameter returnType,
                                  @NotNull MediaType selectedContentType,
                                  @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  @NotNull ServerHttpRequest request,
                                  @NotNull ServerHttpResponse response) {
        if (body instanceof Result<?> result) {
            Long start = (Long) ((ServletServerHttpRequest) request)
                    .getServletRequest()
                    .getAttribute(ResponseTimeInterceptor.START_TIME_ATTR);
            if (start != null) {
                result.setRunTime(System.currentTimeMillis() - start);
            }
        }
        return body;
    }
}
